import Watcher from '../watcher.js'
/**
 * html字符串转dom
 * @param {*} html 
 * @returns 
 */
const htmlStringToElement = (html = "") => {
  const template = document.createElement("template")
  template.innerHTML = html.trim()
  return template.content.firstChild
}

/**
 * 收集器更新操作
 * @param {*} watchers 
 * @param {*} value 
 */
const updateWatcher = (watchers = [], value, type) => {
  if (type) {
    watchers.forEach((watcher) => {
      watcher.arrayUpdate(value, type)
    })
  } else {
    watchers.forEach((watcher) => {
      watcher.update(value)
    })
  }
}

/**
 * 将属性值绑定到vue实例上
 * @param {*} vueInstance 
 * @param {*} obj 
 */
const bindProperties = (vueInstance, obj) => {
  for (let key of Object.keys(obj)) {
    vueInstance[key] = obj[key]
  }
}

/**
 * 初始化计算属性
 * @param {*} vueInstance 
 * @param {*} obj 
 */
const initComputed = (vueInstance, obj) => {
  for (let key of Object.keys(obj)) {
    initWatcher(key, vueInstance, node, 'value') // 收集器初始化并收集相关node
  }
}

/**
 * key为数组 ? 获取最后子节点key对应到组件实例中的值 : 获取对应key组件实例中的值
 * @param {*} key
 * @param {*} data
 * @param {*} callBack
 * @returns 
 */
const getInstanceValue = (key, data, callBack) => {
  try {
    if (Object.prototype.toString.call(key) === '[object Array]') {
      if (key.length === 1) {
        if (callBack) {
          callBack()
        }
        return data[key[0]]
      } else {
        return key.reduce((prev, property) => {
          if (callBack) {
            callBack(property)
          }
          return prev[property]
        }, data)
      }
    } else {
      if (callBack) {
        callBack()
      }
      return data[key]
    }
  } catch (e) {
    console.warn(`lve.js提示：获取实例值报错， 报错key为${key}`);
    return ''
  }
}

/**
 * watcher收集器初始化并收集值
 * @param {*} key 
 * @param {*} vueInstance 当前组件对象实例
 * @param {*} node 当前dom节点
 * @param {*} attribute dom属性绑定
 * @param {*} template dom textContent文本值
 */
const initWatcher = (key, vueInstance, node, attribute, template) => {
  const len = key.length
  const firstKey = key[0]
  if (len > 1) { // 引用类型变量
    const lastKey = key[len - 1]
    vueInstance.$watchers[firstKey] = vueInstance.$watchers[firstKey] || {} // 初始化收集器
    vueInstance.$watchers[firstKey][lastKey] = vueInstance.$watchers[firstKey][lastKey] || [] // 初始化收集器
    vueInstance.$watchers[firstKey][lastKey].push(new Watcher(vueInstance, node, attribute, template));
  } else { // 基本类型变量
    vueInstance.$watchers[firstKey] = vueInstance.$watchers[firstKey] || [] // 初始化收集器
    vueInstance.$watchers[firstKey].push(new Watcher(vueInstance, node, attribute, template));
  }
}

/**
 * 判断某属性是否为对象的属性
 * @param {*} parent 
 * @param {*} key 
 */
const deepAttributeInObject = (parent, key) => {
  let flag = false
  const judgeNode = (node) => {
    for (let i in node) {
      if (i === key) {
        flag = true
      } else {
        if (Object.prototype.toString.call(parent[i]) === '[object Object]') {
          judgeNode(node[i], key)
        }
      }
    }
  }
  judgeNode(parent)
  return flag
}

/**
 * 判断当前数据类型
 * @param {*} obj 
 * @returns 
 */
const getDataType = (obj) => {
  const str = Object.prototype.toString.call(obj); // 检测基本类型值，引用类型值的类型
  const map = {
    '[object Boolean]': 'boolean',
    '[object Number]': 'number',
    '[object String]': 'string',
    '[object Function]': 'function',
    '[object Array]': 'array',
    '[object Date]': 'date',
    '[object RegExp]': 'regExp',
    '[object Undefined]': 'undefined',
    '[object Null]': 'null',
    '[object Object]': 'object'
  };
  if(obj instanceof Element){
    return 'element';
  }
  return map[str];
}

/**
 * 将对象、null、undefined替换成空白字符
 * @param {*} obj 
 */
const replaceObjToBlank = (obj) => {
  const map = {
    'null': 'null',
    '[object Object]': '\[object Object\]',
    'undefined': 'undefined'
  }
  const type = getDataType(obj)
  let res = ''
  if (type === 'string') { // 当设置值为
    const reg = new RegExp(`/(${Object.values(map).join('|')})/`, 'gm')
    res = obj.replaceAll(obj.match(reg), '') // 将所有需转换的字符全都转成空白字符
  } else if (type === 'object') {
    res = obj.toString().replaceAll(reg, '')
  }
  return res
}

/**
 * 清除父节点下非空节点
 * @param {*} ele 
 */
const clearWhitespace = (ele) => {
  for(var i=0;i<ele.childNodes.length;i++){
      var node=ele.childNodes[i];
      if(node.nodeType==3 && !/\S/.test(node.nodeValue)){ // 空白节点首先是文本节点， \S 为匹配非空字符
          node.parentNode.removeChild(node)
      }
  }
}

/**
 * 判断当前字符串是变量还是表达式
 * @param {*} string 字符串
 * @returns str
 */
const isExpressionOrVariable = (string) => {
  if (window.eval) {
    try {
      eval(string);
    } catch (error) {
      return 'variable';
    }
    return 'expression';
  } else {
    const reg = /^[a-zA-Z_][a-zA-Z0-9_]*(\s*[\+\-\*/]\s*[a-zA-Z_][a-zA-Z0-9_]*)*$/
    if (string.match(reg)) {
      return 'expression'; 
    } else {
      return 'variable';
    }
  }
}

/**
 * 判断当前运算符类型
 * @param {*} str 字符串
 * @returns str
 */
const checkExpressionType = (str) => {
  const ternaryOperatorPattern = /(?:[^\?]+)?\?[^\:]*:[^;]*/;
  const nullishCoalescingOperatorPattern = /(?:[^\?]+)?\?\?[^\;]*/;
  const optionalChainingOperatorPattern = /(?:[^\?]+)?\?\.[^\;]*/;
  // 三目运算符
  if (ternaryOperatorPattern.test(str)) {
    return 'ternaryOperatorPattern';
  // 空值合并运算符
  } else if (nullishCoalescingOperatorPattern.test(str)) {
    return 'nullishCoalescingOperatorPattern';
  // 可选链操作符
  } else if (optionalChainingOperatorPattern.test(str)) {
    return 'optionalChainingOperatorPattern';
  } else {
    return '';
  }
}

/**
 * 分别提取三目运算符中的各个变量
 * @param {*} str 字符串
 * @returns Object 分别是三个变量
 */
const extractTernaryVariables = (str) => {
  const ternaryPattern = /([^?]+)\?([^:]+):([^;]+)/;
  const matches = str.match(ternaryPattern);
  if (matches) {
    const condition = matches[1].trim();
    const expr1 = matches[2].trim();
    const expr2 = matches[3].trim();
    return {
      condition,
      expr1,
      expr2
    };
  }
  return null; // 没有匹配到三目运算符
}

/**
 * 分别提取空值合并运算符中的各个变量
 * @param {*} str 字符串
 * @returns  Object 分别是变量和默认值
 */
const extractNullishCoalescingVariables = (str) => {
  const nullishPattern = /([^?]+)\?\?([^;]+)/;
  const matches = str.match(nullishPattern);
  if (matches) {
    const value = matches[1].trim();
    const defaultValue = matches[2].trim();

    return {
      value,
      defaultValue
    };
  }
  return null; // 没有匹配到空值合并运算符
}

/**
 * 分别提取可选链运算符中的各个变量
 * @param {*} str 字符串
 * @returns  Object 分别是变量和属性
 */
const extractOptionalChainingVariables = (str) => {
  const optionalChainPattern = /([^?.]+)\?\.([^;]+)/;
  const matches = str.match(optionalChainPattern);
  if (matches) {
    const obj = matches[1].trim();
    const prop = matches[2].trim();
    return {
      obj,
      prop
    };
  }
  return null; // 没有匹配到可选链运算符
}

export {
  htmlStringToElement,
  updateWatcher,
  bindProperties,
  getInstanceValue,
  initWatcher,
  deepAttributeInObject,
  getDataType,
  replaceObjToBlank,
  clearWhitespace,
  isExpressionOrVariable,
  checkExpressionType,
  extractTernaryVariables,
  extractNullishCoalescingVariables,
  extractOptionalChainingVariables
}